#!/bin/sh
# -------------------------------------------------------------------------
#    Copyright 2002-2021 National Technology &amp; Engineering Solutions of
#    Sandia, LLC (NTESS).  Under the terms of Contract DE-NA0003525 with
#    NTESS, the U.S. Government retains certain rights in this software.
#
#    This file is part of the Xyce(TM) Parallel Electrical Simulator.
#
#    Xyce(TM) is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Xyce(TM) is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Xyce(TM).
#    If not, see <http://www.gnu.org/licenses/>.
# -------------------------------------------------------------------------
#
#-------------------------------------------------------------------------
#
# Purpose        : Provide a simple mechanism for building plugins out of
#                  Verilog-A files
#
# Special Notes  : See buildplugin.in for original Makefile implementation
#
# Creator        : Zack Galbreath
# Creation Date  : 12/23/2020
#
#-------------------------------------------------------------------------

usage ()
{
    echo "Usage: `basename $0` [options] <veriloginputfile>* destinationdirectory"
    echo "  One or more verilog files must be given."
    echo "  The last argument must be a directory name."
    echo "  Options:"
    echo "    -o <name>:  Name for the plugin."
    echo "                If not given, the name will be Xyce_Plugin_<module>"
    echo "                where <module> is taken from the last verilog input file"
    return
}

runadms()
{
    ${XyceInstDir}/bin/admsXml -D__XYCE__ -x -e ${xmldir}/adms.implicit.xml -e ${xmldir}/xyceVersion_nosac.xml  -e ${xmldir}/xyceBasicTemplates_nosac.xml \
            -e ${xmldir}/xyceAnalogFunction_nosac.xml \
            -e ${xmldir}/xyceHeaderFile_nosac.xml \
            -e ${xmldir}/xyceImplementationFile_nosac.xml $1 \
            >> buildxyceplugin.log 2>&1
    return $?
}

scanargs()
{
    VAFILES=""
    ERRCODE=0
    while [ $# -gt 1 ]
    do
        if [ -f $1 ]
        then
            VAFILES="${VAFILES} $1"
        else
            echo
            echo "ERROR: Input file not found or not regular file:  $1"
            echo
            ERRCODE=1
        fi
        shift
    done
    if [ -d $1 ]
    then
        if [ -w $1 ]
        then
            # Make sure to find the absolute path to the destination dir
            DESTDIR=$(cd -- "$1" && pwd)
        else
            echo
            echo "ERROR:  Directory $1 is not writable by you"
            echo
            ERRCODE=1
        fi
    else
        echo
        echo "ERROR:  Final argument $1 is not a directory."
        echo
        ERRCODE=1
    fi
    return $ERRCODE
}

if [ $# -lt 2 ]
then
    usage
    exit 1
fi


# Absolute path to this script, e.g. /home/user/xyce_install/bin/buildplugin.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/xyce_install/bin
SCRIPTPATH=$(dirname "$SCRIPT")
# Absolute path to Xyce install directory.
XyceInstDir=$(dirname "$SCRIPTPATH")
xmldir=${XyceInstDir}/share

CXX='@CMAKE_CXX_COMPILER@'

echo "buildxyceplugin log begun at `date`\n" > buildxyceplugin.log
echo " script invoked as: \n $0 $@" >> buildxyceplugin.log
echo " ----------------" >> buildxyceplugin.log

# Process options
pluginname=""
while getopts o:dS option
do
    case "$option" in
        o)  pluginname="$OPTARG";;
        [?]) usage
             exit 1
             ;;
    esac
done
shift `echo $OPTIND-1 | bc`

headerstring=""
registerstring=""
CLEANFILES=""
OBJFILES=""

scanargs $@
if [ $? != 0  -o "${VAFILES}x" = "x" ]
then
    usage
    exit 1
fi

cd $DESTDIR

echo "buildxyceplugin is building a plugin from the Verilog-A files:"
echo ${VAFILES}
if [ "${pluginname}x" = "x" ]
then
    echo "The plugin name will be generated automatically from the module name"
    echo "in the last file of this list."
else
    echo "The plugin name will be ${pluginname}.so"
fi

count=0
modules=""

set -- ${VAFILES}
while [ $# -ge 1 ]
do
    input=$1

    if [ -f $input ]
    then
       echo "Generating C++ for Verilog-A input file '$input'..."
       runadms $input
       if [ $? -eq 0 ]
       then
           echo "C++ for Verilog-A input file '$input' generated successfully"
       else
           echo "C++ for Verilog-A input file '$input' failed"
           echo "See buildxyceplugin.log for details"
           exit 1
       fi

       # determine the module name
       module=`ls -rt N_DEV_ADMS*.C | tail -1 | sed -e 's/N_DEV_ADMS\(.*\).C/\1/'`
       echo "Input file $input provides module $module"
       modules=${module}" "${modules}
       echo "#include <N_DEV_ADMS${module}.h>" >> .headerstring_$$
       echo "Xyce::Device::ADMS${module}::registerDevice();" >> .registerstring_$$
       if [ $? -ne 0 ]
       then
           echo "Compilation of N_DEV_ADMS${module}.C failed"
           echo "See buildxyceplugin.log for details"
           exit 1
       else
           CLEANFILES="${CLEANFILES} ${CXXFIL} ${OBJFIL} N_DEV_ADMS${module}.h"
       fi
       OBJFILES="$OBJFILES N_DEV_ADMS${module}.lo"

       count=`echo $count+1|bc`
    else
        echo "Input file not found:  $input"
        exit 1
    fi
    shift 1
done

echo "C++ codegen for ${count} Verilog-A input files complete."

if [ "x$pluginname" = "x" ]
then
    pluginname=Xyce_Plugin_$module
fi

echo "Generating bootstrap C++ for plugin $pluginname"

echo "#include <Xyce_config.h>" >  ${pluginname}_bootstrap.C
cat .headerstring_$$ >>   ${pluginname}_bootstrap.C
echo "struct Bootstrap ">>   ${pluginname}_bootstrap.C
echo "{">>   ${pluginname}_bootstrap.C
echo "  Bootstrap()" >>   ${pluginname}_bootstrap.C
echo "  {" >>   ${pluginname}_bootstrap.C
cat .registerstring_$$ >>   ${pluginname}_bootstrap.C
echo "  }" >>   ${pluginname}_bootstrap.C
echo "};" >>   ${pluginname}_bootstrap.C
echo "Bootstrap s_bootstrap;" >>   ${pluginname}_bootstrap.C

rm -f .headerstring_$$ .registerstring_$$

# Use CMake to build this plugin.
echo "Building plugin..."
cp ${XyceInstDir}/share/XycePluginProject.cmake ./CMakeLists.txt
cmake -DCMAKE_CXX_COMPILER="@CMAKE_CXX_COMPILER@" -DPLUGIN_NAME="$pluginname" -DXYCE_INSTALL="$XyceInstDir" .
cmake --build .

echo "Done!  Your plugin may now be used by running Xyce with the option '-plugin ${pluginname}.so'"
echo "This plugin provides the Verilog-A modules: $modules"
